import json
import logging
import re

from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
from django.contrib.auth import login
from django.http import JsonResponse
from django.views import View
from django_redis import get_redis_connection

from carts.utils import merge_cart_cookie_to_redis
from oauth.models import OAuthQQUser
from meiduo.utils.utils import generate_access_token, check_access_token
from users.utils import User

logger = logging.getLogger("django")


# Create your views here.

class QQFirstView(View):

    def get(self, request):
        """
        获取QQ登录链接
        :param request: 请求对象
        :return: JSON
        """
        '''获取请求参数'''
        next = request.GET.get("next")  # 记录QQ登录成功后进入的网址

        '''检查请求参数'''
        if not next:
            return JsonResponse({'code': 400, 'errmsg': '请求参数有误'})

        '''获取QQ登录链接'''
        oauth = OAuthQQ(  # 创建OAuthQQ对象
            client_id=settings.QQ_CLIENT_ID,
            client_secret=settings.QQ_CLIENT_SECRET,
            redirect_uri=settings.QQ_REDIRECT_URI,
            state=next
        )
        login_url = oauth.get_qq_url()  # 获取QQ登录链接

        '''返回响应对象'''
        return JsonResponse({
            'code': 0,
            'errmsg': 'OK',
            'login_url': login_url
        })


class QQUserView(View):

    def get(self, request):
        """
        通过QQ登录
        :param request: 请求对象
        :return: JSON
        """
        '''获取请求参数'''
        code = request.GET.get("code")  # 用户成功登录QQ并授权后返回的Authorization Code，10分钟后过期。

        '''检查请求参数'''
        if not code:
            return JsonResponse({'code': 400, 'errmsg': '请求参数有误'})

        '''获取OpenID'''
        oauth = OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,
            client_secret=settings.QQ_CLIENT_SECRET,
            redirect_uri=settings.QQ_REDIRECT_URI,
            state=next
        )  # 创建OAuthQQ对象
        try:
            token = oauth.get_access_token(code)  # 通过Authorization Code获取Access Token
            openid = oauth.get_open_id(token)  # 通过Access Token获取OpenID（用户身份的标识）
        except Exception as e:
            logger.error(e)
            return JsonResponse({'code': 400, 'errmsg': '获取OpenID失败'})

        '''判断OpenID是否绑定用户'''
        try:
            qq_user = OAuthQQUser.objects.get(openid=openid)  # 获取QQ用户对象
        except Exception as e:
            logger.error(e)
            access_token = generate_access_token(openid, expires=600)  # 加密OpenID（用户身份的标识），有效时间为10分钟
            return JsonResponse({
                'code': 300,
                'errmsg': 'OpenID未绑定用户',
                'access_token': access_token
            })

        '''设置状态保持'''
        response = JsonResponse({'code': 0, 'errmsg': 'OK'})  # 创建响应对象
        user = qq_user.user  # 获取用户用户对象
        login(request, user)  # 记录用户登录信息
        request.session.set_expiry(0)  # 用户登陆信息在浏览器关闭之后删除
        response.set_cookie("username", user.username)  # 设置cookie，浏览器关闭之前有效

        '''返回登录成功响应'''
        response = merge_cart_cookie_to_redis(request, response)  # 合并购物车数据
        return response

    def post(self, request):
        """
        绑定用户
        :param request: 请求对象
        :return: JSON
        """
        '''获取请求参数'''
        request_data = json.loads(request.body)  # 获取请求提数据并转换成字典类型
        mobile = request_data.get("mobile")  # 获取用户输入的手机号
        password = request_data.get("password")  # 获取用户输入的密码
        sms_code = request_data.get("sms_code")  # 获取用户输入的短信验证码
        access_token = request_data.get("access_token")  # 获取加密的openid

        '''检查请求参数'''
        if not all([mobile, password, sms_code, access_token]):
            return JsonResponse({'code': 400, 'errmsg': '请求参数有误'})

        '''比对短信验证码'''
        redis_conn = get_redis_connection("verify_code")  # 获取redis二号库对象
        check_sms_code = redis_conn.get(f"sms_code_{mobile}")  # 从数据库获取短信验证码
        if sms_code != check_sms_code.decode():  # 验证用户输入的验证码是否与数据库存储的验证码一致
            return JsonResponse({'code': 400, 'errmsg': '短信验证码错误'})

        '''检查手机号格式'''
        if not re.match(r"^1[3-9]\d{9}$", mobile):
            return JsonResponse({'code': 400, 'errmsg': '手机号码格式错误'})

        '''检查密码格式'''
        if not re.match(r"^[a-zA-Z0-9_]{8,20}$", password):
            return JsonResponse({'code': 400, 'errmsg': '密码格式错误'})

        '''解密OpenID'''
        openid = check_access_token(access_token)  # 解密OpenID
        if openid is None:
            return JsonResponse({'code': 400, 'errmsg': 'access_token错误'})

        '''检查手机号是否已注册'''
        try:
            user = User.objects.get(mobile=mobile)  # 根据手机号码获取用户对象
        except Exception as e:  # 如果手机号不存在则新建账户
            logger.error(e)
            user = User.objects.create_user(username=f"MD{mobile}", mobile=mobile, password=password)  # 创建账户存储用户信息
        else:
            if OAuthQQUser.objects.filter(user=user).count() > 0:  # 检查手机号是否已绑定QQ
                OAuthQQUser.objects.get(user=user).delete()  # 如果用户已经绑定了其他QQ账号则解除绑定关系

        '''openid与账户进行绑定'''
        OAuthQQUser.objects.create(user=user, openid=openid)  # 存储用户openid并绑定账户

        '''设置状态保持'''
        response = JsonResponse({'code': 0, 'errmsg': 'OK'})  # 创建响应对象
        login(request, user)  # 记录用户登录信息
        request.session.set_expiry(0)  # 用户登陆信息在浏览器关闭之后删除
        response.set_cookie("username", user.username)  # 设置cookie，浏览器关闭之前有效

        '''返回绑定成功响应'''
        response = merge_cart_cookie_to_redis(request, response)  # 合并购物车数据
        return response
